/**
 * 
 */
package info.niwota.start.app;

import info.niwota.start.Intents;
import info.niwota.start.Preferences;
import info.niwota.start.ResourceInfo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;

/**
 * @author qiangli
 * 
 */
public final class AppLoader {
	private static final int MAX_RECENT_TASKS = 12;

	private static ApplicationInfo getApplicationInfo(PackageManager manager,
			Intent intent) {
		final ResolveInfo ri = manager.resolveActivity(intent, 0);
		if (ri == null) {
			return null;
		}
		final ApplicationInfo info = new ApplicationInfo();
		final ActivityInfo activityInfo = ri.activityInfo;
		info.icon = activityInfo.loadIcon(manager);
		if (info.title == null || info.title.length() == 0) {
			info.title = activityInfo.loadLabel(manager).toString();
		}
		if (info.title == null) {
			info.title = "";
		}
		return info;
	}

	public static int getApplicationCount(Context ctx, String category) {
		PackageManager pm = ctx.getPackageManager();
		final List<ResolveInfo> apps = queryApplication(pm, category);
		return (apps == null ? 0 : apps.size());
	}
	
	public static List<ResourceInfo> loadAll(Context ctx) {
		ArrayList<ResourceInfo> list = new ArrayList<ResourceInfo>();
		loadApplication(ctx, list, Intent.CATEGORY_LAUNCHER);
		return list;
	}
	
	public static List<ResourceInfo> loadApplication(Context ctx, String category) {
		ArrayList<ResourceInfo> list = new ArrayList<ResourceInfo>();
		loadApplication(ctx, list, category);
		return list;
	}
	
	public static void loadApplicationByKey(Context ctx,
			List<ResourceInfo> list, String key) {
		final String cat = ("powerup".equals(key) ? Intents.CATEGORY_RESTRICTED : Intent.CATEGORY_LAUNCHER);
		loadApplication(ctx, list, cat);
	}
	
	public static void loadApplication(Context ctx,
			List<ResourceInfo> list, String catetory) {
		PackageManager pm = ctx.getPackageManager();
		List<ResolveInfo> apps = queryApplication(pm, catetory);
		//
		Collections.sort(apps, new ResolveInfo.DisplayNameComparator(pm));
		
		if (apps == null) {
			return;
		}
		final int cnt = apps.size();
		for (int i = 0; i < cnt; i++) {
			ApplicationInfo info = new ApplicationInfo();
			ResolveInfo ri = apps.get(i);
			info.title = ri.loadLabel(pm).toString();
			
			ComponentName cn = new ComponentName(
					ri.activityInfo.applicationInfo.packageName,
					ri.activityInfo.name);
			info.setActivity(cn, Intent.FLAG_ACTIVITY_NEW_TASK
					| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
			info.icon = ri.activityInfo.loadIcon(pm);
			info.id = makeId(cn);
			
			list.add(info);
		}
	
	}

	private static List<ResolveInfo> queryApplication(PackageManager pm, String category) {
		Intent mi = new Intent(Intent.ACTION_MAIN, null);
		mi.addCategory(category);
		final List<ResolveInfo> apps = pm.queryIntentActivities(
				mi, 0);
		return apps;
	}
	
	public static List<ResourceInfo> loadRecent(Context ctx) {
		ArrayList<ResourceInfo> list = new ArrayList<ResourceInfo>();
		AppLoader.loadRecent(ctx, list);
		return list;
	}

	public static void loadRecent(Context ctx, ArrayList<ResourceInfo> list) {
		final PackageManager pm = ctx.getPackageManager();
		final ActivityManager tm = (ActivityManager) ctx
				.getSystemService(Activity.ACTIVITY_SERVICE);
		final List<ActivityManager.RecentTaskInfo> tasks = tm
				.getRecentTasks(MAX_RECENT_TASKS, 0);

		if (tasks == null) {
			return;
		}
		final int cnt = tasks.size();
		for (int i = 0; i < cnt; i++) {
			final Intent intent = tasks.get(i).baseIntent;
			if (Intent.ACTION_MAIN.equals(intent.getAction())
					&& !intent.hasCategory(Intent.CATEGORY_HOME)) {
				ApplicationInfo info = getApplicationInfo(pm, intent);
				if (info != null) {
					info.intent = intent;
					info.type = Types.RECENT;
					info.id = makeId(intent.getComponent());
					list.add(info);
				}
			}
		}
	}

	private static String makeId(ComponentName c) {
		String n = c.toString().replaceAll("/", "_");
		return encodePath(n);
	}

	private static String encodePath(String s) {
		try {
			return URIEncoder.encodeURI(s);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s;
	}


	private static List<ResourceInfo> loadApps(Context ctx, String data, String category) {
		ArrayList<ResourceInfo> apps = new ArrayList<ResourceInfo>();
		ArrayList<ResourceInfo> list = new ArrayList<ResourceInfo>();
		if (TextUtils.isEmpty(data)) {
			return list;
		}
		loadApplication(ctx, apps, category);
		String[] sa = toStringArray(data);
		for (int i = 0; i < sa.length; i++) {
			String sai = sa[i];
			for (ResourceInfo a : apps) {
				String s = a.getIntent().getComponent().toString();
				if (sai.equals(s)) {
					list.add(a);
					break;
				}
			}
		}
		return list;
	}
	
	private static List<ResourceInfo> load(Context ctx, String key, String category) {
		String apps = Preferences.getApps(ctx, key);
		return loadApps(ctx, apps, category);
	}
	
	public static List<ResourceInfo> loadPowerup(Context ctx) {
		return load(ctx, "powerup", Intents.CATEGORY_RESTRICTED);
	}
	
	public static List<ResourceInfo> loadStartup(Context ctx) {
		return load(ctx, "startup", Intent.CATEGORY_LAUNCHER);
	}

	public static List<ResourceInfo> loadStatusbar(Context ctx) {
		return load(ctx, "statusbar", Intent.CATEGORY_LAUNCHER);
	}
	
	public static List<? extends Object> loadStarred(Context ctx) {
		return load(ctx, "favorite", Intent.CATEGORY_LAUNCHER);
	}
	

	public static String[] toStringArray(String str) {
		String[] tos = str.split("\t");
		for (int i = 0; i < tos.length; i++) {
			tos[i] = tos[i].trim(); // remove extra spaces if any
		}
		return tos;
	}

	public static String toString(ArrayList<ResourceInfo> list) {
		if (list == null) {
			return null;
		}
		Iterator<ResourceInfo> i = list.iterator();
		if (!i.hasNext()) {
			return null;
		}
		ResourceInfo a = i.next();
		Intent it = a.getIntent();
		String cs = it.getComponent().toString();
		StringBuilder sb = new StringBuilder(cs);
		while (i.hasNext()) {
			a = i.next();
			it = a.getIntent();
			cs = it.getComponent().toString();
			sb.append("\t ");
			sb.append(cs);
		}
		final String str = sb.toString();
		return str;
	}
	private AppLoader() {
	}

}
